package cn.eva.service.Impl.admin;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.scheduling.annotation.Async;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import cn.eva.common.LayuiTableResult;
import cn.eva.common.ResultJosn;
import cn.eva.common.enums.StudentStatus;
import cn.eva.dao.EvaStudentMapper;
import cn.eva.dao.SysRoleMapper;
import cn.eva.dao.SysUserRoleMapper;
import cn.eva.entity.EvaStudent;
import cn.eva.entity.SysRole;
import cn.eva.entity.SysUserRoleKey;
import cn.eva.example.EvaStudentExample;
import cn.eva.example.EvaStudentExample.Criteria;
import cn.eva.example.SysRoleExample;
import cn.eva.example.SysUserRoleExample;
import cn.eva.service.admin.SysStudentService;
import cn.eva.service.admin.UserRoleService;
import cn.eva.utils.UUIDUtils;

/**
 * 学生接口实现类
 * 
 * @author wzh
 *
 */
@Service
public class SysStudentServiceImpl implements SysStudentService {

    private final static String xls = "xls";

    @Autowired
    private EvaStudentMapper studentMapper;

    @Autowired
    private SysRoleMapper roleMapper;

    @Autowired
    private SysUserRoleMapper userRoleMapper;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private UserRoleService userRoleService;

    /**
     * 新增学生
     */
    @Override
    @Transactional
    public ResultJosn add(EvaStudent student) {
        List<EvaStudent> list = new ArrayList<>();
        if (null != this.checkStudentNo(student.getsNo())) {
            throw new IllegalArgumentException(student.getsNo() + "已存在！");
        }

        student.setsId(UUIDUtils.getUUID());
        student.setsPass(passwordEncoder.encode(student.getsPass()));
        student.setCreateTime(new Date());
        student.setUpdateTime(new Date());
        studentMapper.insertSelective(student);
        list.add(student);
        this.saveStudentRole(list);
        return new ResultJosn(HttpStatus.OK.value(), HttpStatus.OK.getReasonPhrase(), null);
    }

    private final static String xlsx = "xlsx";

    /**
     * 单个、批量删除
     */
    @Override
    @Transactional
    public ResultJosn delete(List<String> sId) {
        EvaStudentExample example = new EvaStudentExample();
        example.createCriteria().andSIdIn(sId);
        userRoleService.delByUids(sId);
        studentMapper.deleteByExample(example);
        return new ResultJosn(HttpStatus.OK.value(), HttpStatus.OK.getReasonPhrase(), "删除成功");
    }

    /**
     * @Title 修改学生信息
     */
    @Override
    @Transactional
    public ResultJosn update(EvaStudent student) {
        if (StringUtils.isBlank(student.getsId())) {
            throw new IllegalArgumentException("sId错误！");
        }
        EvaStudent check = this.checkStudentNo(student.getsNo());
        if (null != check && !(check.getsId()).equals(student.getsId())) {
            throw new IllegalArgumentException("学生学号已存在！");
        }
        student.setsPass(passwordEncoder.encode(student.getsPass()));
        studentMapper.updateByPrimaryKeySelective(student);
        return new ResultJosn(HttpStatus.OK.value(), HttpStatus.OK.getReasonPhrase(), "修改成功");
    }

    /**
     * @Title 查询全部学生 可以根据学生学号进行模糊查询
     */
    @Override
    public LayuiTableResult select(EvaStudent student, Integer page, Integer pageSize) {
        LayuiTableResult resultJosn = new LayuiTableResult();
        // 构造条件
        EvaStudentExample example = new EvaStudentExample();
        example.setOrderByClause("create_time DESC");
        Criteria criteria = example.createCriteria();
        // 班级号
        if (StringUtils.isNotBlank(student.getClassId())) {
            criteria.andClassIdLike("%" + student.getClassId() + "%");
        }
        // 学号
        if (StringUtils.isNotBlank(student.getsNo())) {
            criteria.andSNoLike("%" + student.getsNo() + "%");
        }
        // 姓名
        if (StringUtils.isNotBlank(student.getsName())) {
            criteria.andSNameLike("%" + student.getsName() + "%");
        }
        // 开启分页查找
        PageHelper.startPage(page, pageSize);
        List<EvaStudent> list = studentMapper.selectByExample(example);
        PageInfo<EvaStudent> pageInfo = new PageInfo<>(list, pageSize);
        resultJosn.setCode(HttpStatus.OK.value());
        resultJosn.setMessage(HttpStatus.OK.getReasonPhrase());
        resultJosn.setCount(pageInfo.getTotal());
        resultJosn.setData(pageInfo.getList());
        return resultJosn;
    }

    @Override
    public ResultJosn selectBysId(String sId) {
        if (StringUtils.isBlank(sId)) {
            throw new IllegalArgumentException("sId 错误！");
        }
        EvaStudent student = studentMapper.selectByPrimaryKey(sId);
        return new ResultJosn(HttpStatus.OK.value(), HttpStatus.OK.getReasonPhrase(), student);
    }

    /**
     * 根据学生学号查找是否重复
     * 
     * @param sNo
     * @return
     */
    public EvaStudent checkStudentNo(String sNo) {
        EvaStudentExample example = new EvaStudentExample();
        example.createCriteria().andSNoEqualTo(sNo);
        List<EvaStudent> list = studentMapper.selectByExample(example);
        if (CollectionUtils.isEmpty(list)) {
            return null;
        }
        return (EvaStudent) list.get(0);
    }

    /**
     * excel批量导入学生信息
     * <p>
     * Title: importExcel
     * </p>
     * <p>
     * Description:
     * </p>
     * 
     * @param file
     * @return
     * @throws IOException
     * @see cn.eva.service.admin.SysStudentService#importExcel(org.springframework.web.multipart.MultipartFile)
     */
    @Override
    @Transactional
    public ResultJosn importExcel(MultipartFile file) throws IOException {
        List<EvaStudent> allLists = new ArrayList<>();
        List<EvaStudent> addLists = new ArrayList<>();
        List<EvaStudent> updateLists = new ArrayList<>();
        // 初始化、判断
        String fileName = file.getOriginalFilename();
        InputStream inputStream = file.getInputStream();
        Workbook workbook = null;
        if (fileName.endsWith(xls)) {
            workbook = new HSSFWorkbook(inputStream);
        } else if (fileName.endsWith(xlsx)) {
            workbook = new XSSFWorkbook(inputStream);
        } else {
            throw new IllegalArgumentException("您上传的不是xls或者xlsx的excel表");
        }
        // 解析数据
        // 获取Excel工作表
        Sheet sheet = workbook.getSheetAt(0);
        if (sheet == null) {
            throw new IllegalArgumentException("excel数据为空");
        }
        EvaStudent evaStudent = null;
        Date date = new Date();
        for (int r = 1; r <= sheet.getLastRowNum(); r++) {
            Row row = sheet.getRow(r);
            if (row == null) {
                // 某一行为空，继续下一行
                continue;
            }
            evaStudent = new EvaStudent();
            Cell cell0 = row.getCell(0);
            if (cell0 == null) {
                continue;
            }
            cell0.setCellType(Cell.CELL_TYPE_STRING);
            // 班级号
            String clssId = cell0.getStringCellValue();
            Cell cell1 = row.getCell(1);
            if (cell1 == null) {
                continue;
            }
            cell1.setCellType(Cell.CELL_TYPE_STRING);
            // 学号
            String sNo = cell1.getStringCellValue();
            Cell cell2 = row.getCell(2);
            if (cell2 == null) {
                continue;
            }
            cell2.setCellType(Cell.CELL_TYPE_STRING);
            // 姓名
            String sName = cell2.getStringCellValue();
            Cell cell3 = row.getCell(3);
            if (cell3 == null) {
                continue;
            }
            cell3.setCellType(Cell.CELL_TYPE_STRING);
            // 学生性别（1男0女）
            String sSex = cell3.getStringCellValue();
            if (StringUtils.equals(sSex, "男")) {
                sSex = "1";
            } else if (StringUtils.equals(sSex, "女")) {
                sSex = "0";
            } else {
                throw new IllegalArgumentException("导入失败（第" + (r + 1) + "行，请规范填写）" + sName + "的性别(男或女)");
            }
            Cell cell4 = row.getCell(4);
            if (cell4 == null) {
                continue;
            }
            // 学生类型（1在校2退学3休学）
            cell4.setCellType(Cell.CELL_TYPE_STRING);
            String sType = cell4.getStringCellValue();
            if (StringUtils.equals(sType, StudentStatus.IN.getName())) {
                sType = StudentStatus.IN.getCode();
            } else if (StringUtils.equals(sType, StudentStatus.OUT.getName())) {
                sType = StudentStatus.OUT.getCode();
            } else if (StringUtils.equals(sType, StudentStatus.Suspension.getName())) {
                sType = StudentStatus.Suspension.getCode();
            } else {
                throw new IllegalArgumentException("导入失败（第" + (r + 1) + "行，请规范填写）" + sName + "的学生类别(在校、退学或休学)");
            }

            evaStudent.setsId(sNo + UUIDUtils.getUUID());
            evaStudent.setClassId(clssId);
            evaStudent.setsNo(sNo);
            evaStudent.setsPass(passwordEncoder.encode(sNo));
            evaStudent.setsName(sName);
            evaStudent.setsSex(sSex);
            evaStudent.setsType(sType);
            evaStudent.setCreateTime(date);
            evaStudent.setUpdateTime(date);

            allLists.add(evaStudent);
        }
        // 导入数据库之前分区
        for (EvaStudent stu : allLists) {
            // 根据学号查询
            EvaStudentExample example = new EvaStudentExample();
            example.createCriteria().andSNoEqualTo(stu.getsNo());
            List<EvaStudent> list = studentMapper.selectByExample(example);
            if (CollectionUtils.isEmpty(list)) {
                // 插入数据
                addLists.add(stu);
            } else {
                // 更新数据
                updateLists.add(stu);
            }
        }
        // 批量导入更新
        if (addLists.size() > 0) {
            studentMapper.insertBatch(addLists);
        }
        if (updateLists.size() > 0) {
            studentMapper.updateBatch(updateLists);
        }
        this.saveStudentRole(allLists);
        return new ResultJosn(HttpStatus.OK.value(),
                "成功导入" + addLists.size() + "学的生信息，更新了" + updateLists.size() + "条学生的信息", "导入成功");
    }

    /**
     * <p>
     * Title: exportExcel
     * </p>
     * <p>
     * Description: excel批量导入学生信息
     * </p>
     * 
     * @param type
     * @throws IOException
     * @see cn.eva.service.admin.SysStudentService#exportExcel(java.lang.String)
     */
    @Override
    public ByteArrayOutputStream exportExcel(EvaStudent evaStudent, String type) throws IOException {
        Workbook workbook = null;
        if (StringUtils.equals(type, xls)) {
            workbook = new HSSFWorkbook();
        } else if (StringUtils.equals(type, xlsx)) {
            workbook = new XSSFWorkbook();
        } else {
            throw new IllegalArgumentException("请选择正确的导出格式");
        }
        // 创建excel
        String title = evaStudent.getClassId();
        Sheet sheet = workbook.createSheet(StringUtils.isNotBlank(title) ? title : "" + "学生基本信息表");
        // 创建第一行（标题行）
        this.initTitle(sheet);
        // 数据库查询数据
        EvaStudentExample example = new EvaStudentExample();
        example.setOrderByClause("s_no ASC");
        Criteria criteria = example.createCriteria();
        if (StringUtils.isNoneBlank(evaStudent.getClassId())) {
            criteria.andClassIdEqualTo(evaStudent.getClassId());
        }
        List<EvaStudent> list = studentMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(list)) {
            int size = list.size();
            for (int i = 0; i < size; i++) {
                EvaStudent stu = list.get(i);
                // 行
                Row row = sheet.getRow((i + 1));
                if (row == null) {
                    row = sheet.createRow((i + 1));
                }
                // 班级号
                Cell cell0 = row.getCell(0);
                if (cell0 == null) {
                    cell0 = row.createCell(0, Cell.CELL_TYPE_STRING);
                }
                cell0.setCellValue(stu.getClassId());
                // 学号
                Cell cell1 = row.getCell(1);
                if (cell1 == null) {
                    cell1 = row.createCell(1, Cell.CELL_TYPE_STRING);
                }
                cell1.setCellValue(stu.getsNo());
                // 姓名
                Cell cell2 = row.getCell(2);
                if (cell2 == null) {
                    cell2 = row.createCell(2, Cell.CELL_TYPE_STRING);
                }
                cell2.setCellValue(stu.getsName());
                // 性别
                Cell cell3 = row.getCell(3);
                if (cell3 == null) {
                    cell3 = row.createCell(3, Cell.CELL_TYPE_STRING);
                }
                String sSex = stu.getsSex();
                if (StringUtils.equals(sSex, "1")) {
                    cell3.setCellValue("男");
                } else if (StringUtils.equals(sSex, "0")) {
                    cell3.setCellValue("女");
                } else {
                    cell3.setCellValue("");
                }
                // 类别
                Cell cell4 = row.getCell(4);
                if (cell4 == null) {
                    cell4 = row.createCell(4, Cell.CELL_TYPE_STRING);
                }
                String sType = stu.getsType();
                if (StringUtils.equals(sType, StudentStatus.IN.getCode())) {
                    cell4.setCellValue(StudentStatus.IN.getName());
                } else if (StringUtils.equals(sType, StudentStatus.OUT.getCode())) {
                    cell4.setCellValue(StudentStatus.OUT.getName());
                } else if (StringUtils.equals(sType, StudentStatus.Suspension.getCode())) {
                    cell4.setCellValue(StudentStatus.Suspension.getName());
                } else {
                    cell4.setCellValue("");
                }
            }
        }
        // 写出结果
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        workbook.write(baos);
        return baos;
    }

    private void initTitle(Sheet sheet) {
        Row headerRow = sheet.createRow(0);
        Cell cell0 = headerRow.createCell(0, Cell.CELL_TYPE_STRING);
        cell0.setCellValue("班级号");
        Cell cell1 = headerRow.createCell(1, Cell.CELL_TYPE_STRING);
        cell1.setCellValue("学号");
        Cell cell2 = headerRow.createCell(2, Cell.CELL_TYPE_STRING);
        cell2.setCellValue("姓名");
        Cell cell3 = headerRow.createCell(3, Cell.CELL_TYPE_STRING);
        cell3.setCellValue("性别");
        Cell cell4 = headerRow.createCell(4, Cell.CELL_TYPE_STRING);
        cell4.setCellValue("学生类别");
    }

    /**
     * 
     * @Title: saveStudentRole @Description: 保存学生角色 @param: @param stus @return:
     * void @throws
     */
    @Async
    @Transactional
    private void saveStudentRole(List<EvaStudent> stus) {
        // 查询出学生唯一标识的角色id
        SysRoleExample example = new SysRoleExample();
        example.createCriteria().andRNameEqualTo("STUDENT");
        List<SysRole> rids = roleMapper.selectByExample(example);
        if (!CollectionUtils.isEmpty(rids)) {
            // 先删除
            List<String> sids = stus.parallelStream().map(EvaStudent::getsId).collect(Collectors.toList());
            SysUserRoleExample example1 = new SysUserRoleExample();
            example1.createCriteria().andUidIn(sids);
            userRoleMapper.deleteByExample(example1);
            // 插入
            Long roleId = rids.get(0).getrId();
            for (String sid : sids) {
                SysUserRoleKey record = new SysUserRoleKey(sid, roleId);
                userRoleMapper.insert(record);
            }
        }
    }

}